#include <iostream>

using namespace std;

class Product {
public:
    virtual ~Product() {
        // 销毁组件 A,B,C
        ComponentA = 0;
        ComponentB = 0;
        ComponentC = 0;
    }

public:
    int ComponentA = 0;
    int ComponentB = 0;
    int ComponentC = 0;

public:
    virtual void showProductInfo() = 0;
};

class ProductBuilder {
public:
    virtual ~ProductBuilder() = default;

public:
    virtual void ConstructComponentA() = 0;

    virtual void ConstructComponentB() = 0;

    virtual void ConstructComponentC() = 0;

protected:
    Product *product = nullptr;

public:
    Product *getProduct() {
        return product;
    }
};

class Director {
public:
    virtual ~Director() {
        delete builder;
    }

    explicit Director(ProductBuilder *builder) : builder(builder) {}

private:
    ProductBuilder *builder;

public:
    Product *construct() {
        builder->ConstructComponentA();
        builder->ConstructComponentB();
        builder->ConstructComponentC();

        return builder->getProduct();
    }
};

class ProductA : public Product {
public:
    ~ProductA() override = default;

public:
    void showProductInfo() override {
        cout << "Show Product A Info!" << endl;
        cout << "Component A = " << ComponentA << endl;
        cout << "Component B = " << ComponentB << endl;
        cout << "Component C = " << ComponentC << endl;
    }
};

class ProductABuilder : public ProductBuilder {
public:
    ProductABuilder() {
        product = new ProductA();
    }

public:
    void ConstructComponentA() override {
        product->ComponentA = rand() % 100;
    }

    void ConstructComponentB() override {
        product->ComponentB = rand() % 100;
    }

    void ConstructComponentC() override {
        product->ComponentC = rand() % 100;
    }
};

class ProductB : public Product {
public:
    ~ProductB() override = default;

public:
    void showProductInfo() override {
        cout << "Show Product B Info!" << endl;
        cout << "Component A = " << ComponentA << endl;
        cout << "Component B = " << ComponentB << endl;
        cout << "Component C = " << ComponentC << endl;
    }
};

class ProductBBuilder : public ProductBuilder {
public:
    ProductBBuilder() {
        product = new ProductB();
    }

public:
    void ConstructComponentA() override {
        product->ComponentA = rand() % 100 + 100;
    }

    void ConstructComponentB() override {
        product->ComponentB = rand() % 100 + 100;
    }

    void ConstructComponentC() override {
        product->ComponentC = rand() % 100 + 100;
    }
};

void test01() {
    Product *product = nullptr;
    ProductBuilder *builder = nullptr;
    Director *director = nullptr;

    builder = new ProductABuilder();
    director = new Director(builder);
    product = director->construct();

    product->showProductInfo();

    delete director, product;

    cout << endl;
}

void test02() {
    Product *product = nullptr;
    ProductBuilder *builder = nullptr;
    Director *director = nullptr;

    builder = new ProductBBuilder();
    director = new Director(builder);
    product = director->construct();

    product->showProductInfo();

    delete director, product;

    cout << endl;
}

int main() {
    test01();

    test02();
}